<!doctype html>
<html lang="zh_cn" itemscope itemtype="http://schema.org/Person">
<head>
            <meta charset="utf-8">
        <!-- Site Meta Data -->
        <title>[原创]Nginx Http Server读书笔记</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="技术博客,涉及Java/PHP/Python/Javascript等,聊聊程序,聊聊生活,聊聊事实,聊聊育儿">
        <meta name="keywords" content="编码经验,技术分享,生活积累,实事评说">
        <meta name="author" content="布丁缘">

        <link rel="shortcut icon" href="">

        <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
        <!-- Style Meta Data -->
        <link rel="stylesheet" href="https://www.ddkiss.com/theme/css/style.css" type="text/css"/>
        <link rel="stylesheet" href="https://www.ddkiss.com/theme/css/pygments.css" type="text/css"/>

        <!-- Feed Meta Data -->
            <link href="https://www.ddkiss.com/feeds/all.atom.xml" type="application/atom+xml" rel="alternate"
                  title="一个程序员的简单生活 ATOM Feed"/>


    <meta name="keywords" content="">
    <link rel="stylesheet" href="//dn-coding-net-public-file.qbox.me/Coding-Comments/v0.1.0/default.css">
</head>

<body>
<!-- Sidebar -->
<aside>
    <center><h1><a href="/" style="color:#fff"><img id="avatar" src="/images/avatar.jpg"></a></h1></center>
        <p>一个程序员的简单生活</p>
    <br>
    <nav class="nav">
        <ul class="list-bare">
                <li><a class="nav__link" href="https://www.ddkiss.com/category/chang-yong-ji-qiao.html">常用技巧</a></li>
                <li><a class="nav__link" href="https://www.ddkiss.com/category/kai-fa-huan-jing.html">开发环境</a></li>
                <li><a class="nav__link" href="https://www.ddkiss.com/category/sheng-huo-dian-di.html">生活点滴</a></li>

                <li><a class="nav__link" href="/pages/books.html">书单</a></li>
                <li><a class="nav__link" href="/pages/movies.html">影单</a></li>
                <li><a class="nav__link" href="/pages/downloads.html">下载</a></li>
                <li><a class="nav__link" href="/pages/about.html">关于我</a></li>


        </ul>
    </nav>


    <form>
      <input type="text"  id="bdcsMain"/>
    </form>

</aside>

<!-- Content -->
<article>
  <main>
    <nav>
      <a href="/">首页</a>
      <a href="/archives.html">归档</a>
      <a href="/categories.html">分类</a>
      <a href="/tags.html">标签</a>
      <a href="/pages/about.html">关于我</a>
    </nav>
  </main>
    <section id="content">
        <article>
            <h2 class="post_title post_detail"><a href="https://www.ddkiss.com/archives/29.html" rel="bookmark"
                                                  title="Permalink to [原创]Nginx Http Server读书笔记">[原创]Nginx Http Server读书笔记</a></h2>

            <div class="post_list">
                <span>作者：</span><a href="https://www.ddkiss.com/author/bu-ding-yuan.html">布丁缘</a>
                <span class="post_category">分类：<a href="https://www.ddkiss.com/category/kai-fa-huan-jing.html" rel="bookmark"
                                               title="Permalink to 开发环境">开发环境</a></span>
                <span class="post_date">  时间：2017-09-24 15:52:00</span>

            </div>
            <div class="entry-content blog-post">
                <h1>前言</h1>
<p>早在2015年5月，我就读了这本书的第一章。当时对nginx还不算了解，看了第一章就没继续了。也许是自己太早陷入配置细节了，后面反而兴趣不大。最近看MySQL5.1手册，其中提到了不要用root配置mysql，即使用root启动也最好带上 --user=usernamexx。突然有了一个疑问，为什么这么做？想到之前这本书的第一部分提到了“最小权限原则”。再看了一遍笔记和书，对这个有了更多的了解。</p>
<h1>问题</h1>
<h2>1. 最小权限原则。</h2>
<p>书里讲到，计算机安全的最基本原则就是最小权限原则。也就是永远不给他多余的权限。试想下，如果一个人只有查看某些文件的权限，但你给了他更多权限，这样会导致系统安全性和完整性被破坏。</p>
<h2>2. 如何赋予权限？</h2>
<p>Linux中有 用户/组/其他 三个权限粒度。最终权限是控制到文件，所以，假设需要控制这个文件的权限，我们怎么做？无非是 r.x.w.-</p>
<ol>
<li>
<p>任何一个人是否可以操作这个文件？ 设置 other 权限为 r 或者 -</p>
</li>
<li>
<p>某一类人是否可以操作这个文件？ 设置 group 权限为 r.w.x.-</p>
</li>
<li>
<p>某个用户是否可以操作这个文件？ 设置 user 权限为 r.w.x.-</p>
</li>
</ol>
<p>但是，有一个用户比较特殊，root用户，也就是超级管理员。上述文件权限对他没有限制。所以，安装mysql 或者nginx时，必须用</p>
<div class="highlight"><pre><span></span>chown -R nginx:nginx /opt/nginx
</pre></div>


<p>这样才能把权限定义得更小，对其他非root账户起到隔离作用。</p>
<h1>第2章</h1>
<h2>1. 用户和组</h2>
<p>如果启动nginx，打开网页，出现"403 Forbidden"错误就说明用户或用户组配置错误。Nginx需要两个级别的进程权限：</p>
<ol>
<li>
<p>master进程。因为OS限制了只有root才可以监听1024以下的端口，通常我们用80，所以必须用root启动master。在配置文件中指定user是不会影响master的权限。</p>
</li>
<li>
<p>worker进程。由配置文件中指定，比如 user nginx nginx。如果不指定，则以 nobody nobody来运行,参考<a href="http://nginx.org/en/docs/ngx_core_module.html#user">这里</a></p>
</li>
</ol>
<p>根据最小权限原则，最好配置user权限。</p>
<h2>2. 如何查看nginx加载的模块？</h2>
<p>通过 nginx -V 查看，比如</p>
<div class="highlight"><pre><span></span>[root@myos nginx]# nginx -V
nginx version: nginx/1.12.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled

configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt=&#39;-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC&#39; --with-ld-opt=&#39;-Wl,-z,relro -Wl,-z,now -pie&#39;
</pre></div>


<h2>3. Http配置(p107)</h2>
<p>包括 http , server, location 的配置。http里可以有多个server，server里面可以有多个location.</p>
<h2>3.1 server_name 的配置</h2>
<ol>
<li>
<p>可以指定一个或多个主机名。</p>
</li>
<li>
<p>可以为空字符串　" ", 或者 _</p>
</li>
<li>
<p>如果以"~"开头，则后面可接正则；反之，则可接通配符。<a href="http://www.cnblogs.com/sujz/archive/2011/12/14/2288164.html">通配符!=正则</a></p>
</li>
</ol>
<p>例如：</p>
<div class="highlight"><pre><span></span>server_name  abc.com
server_name  *abc.com
server_name  ~^abc\.com$
</pre></div>


<p>注意匹配规则：</p>
<ol>
<li>
<p>如果命中，则选中第一个匹配的server</p>
</li>
<li>
<p><strong>如果都没命中，则选中第一个server</strong></p>
</li>
<li>
<p>如果命中两个server,　优先选中　listen xx default　所在server</p>
</li>
<li>
<p>如果不写名字，但又不想默认选中第一个server, 则可以配置一个空字符串名字,比如 <code>server_name  _ " "</code>来指定专门处理这类请求</p>
</li>
</ol>
<h2>3.2 路径和文档</h2>
<ol>
<li>root 指令。定义文档的根目录。可以全局设置，也可以在server里覆盖全局设定</li>
<li>index 指令。定义一个默认页面，比如<code>index index.php index2.php index.html</code></li>
<li>tryfiles 指令。视图找到指定文件，location下使用。比如<code>try_files $uri $uri/ /index.php$is_args$args;</code></li>
</ol>
<h2>3.3 客户端请求(p117)</h2>
<p>keepalive_timeout 指令。使用环境：http,server,location。定义一个时长，在此期间客户端访问服务器不需要再次建立连接。（如何实现？服务端告诉客户端不要断开，重用连接？）</p>
<h2>3.4 模块变量</h2>
<p>具体变量太多，详细看书。例如 $is_args. 如果定义了$args，则它是<code>?</code>;反之，则为空</p>
<h2>3.5 Location区段(p133)</h2>
<p>Location区段是最常用也是最容易糊涂的地方。修饰符比较多，优先级也比较绕。它通过指定的模式与客户端的URI进行匹配。语法为<code>location [=|~|~*|^~|@] pattern {...}</code>。第一个可选参数是一个符号，表示不同的行为。</p>
<h3>1. <code>=</code> 完全精确匹配。</h3>
<p>比如 <code>location = /abc {...}</code>，匹配结果如下</p>
<div class="highlight"><pre><span></span>1. xxx/abc  匹配成功
2. xxx/ABC  匹配成功(看OS层是否区分大小写)
3. xxx/abc/ 匹配失败(结尾多了一个`/`)
4. xxx/abcd 匹配失败(结尾多了个`d`)
</pre></div>


<h3>2. <code>无</code> （啥也不写）则前缀匹配。</h3>
<p>比如 <code>location /abc {...}</code>，匹配结果如下</p>
<div class="highlight"><pre><span></span>1. xxx/abc  匹配成功
2. xxx/ABC  匹配成功
3. xxx/abc/ 匹配成功
4. xxx/abcd 匹配成功
5. xxx/123/abc  匹配失败
6. xxx/abc?name=1&amp;age=12  匹配成功(忽略字符串参数)
</pre></div>


<h3>3. <code>~</code> 正则匹配，区分大小写</h3>
<p>比如 <code>location ~ ^/abc$ {...}</code>，匹配结果如下</p>
<div class="highlight"><pre><span></span>1. xxx/abc 匹配成功
2. xxx/ABC 匹配失败(区分大小写)
3. xxx/abc?name=12 匹配成功(忽略字符串参数)
4. xxx/abc/ 匹配失败
5. xxx/abcd 匹配失败
</pre></div>


<h3>4. <code>~*</code> 正则匹配，不区分大小写</h3>
<p>比如 <code>location ~* ^/abc$ {...}</code>，匹配结果如下</p>
<div class="highlight"><pre><span></span>1. xxx/abc 匹配成功
2. xxx/ABC 匹配成功
3. xxx/abc?name=12 匹配成功(忽略字符串参数)
4. xxx/abc/ 匹配失败
5. xxx/abcd 匹配失败
</pre></div>


<p><strong>注意：</strong>部分操作系统（如windows）本身大小写不敏感，则<code>~</code>和<code>~*</code>一样</p>
<h3>5. <code>^~</code> 前缀匹配，类似于<code>无模式</code>。优先级的处理上有区别，区别在于如果匹配成功，则停止搜索其他模式。</h3>
<h3>6. 查找顺序和优先级</h3>
<p>优先级顺序为 <code>=</code> &gt; <code>无</code> &gt; <code>^~</code> &gt; <code>~</code> 或<code>~*</code>，但这种排序并不准确。默认是按顺序匹配，但优先级的不同会中断这种顺序匹配。</p>
<p><font color=#8B0000 face="黑体"></p>
<h4>如果有多个location, 简单总结：</h4>
<ol>
<li>如果匹配到<code>=</code>，匹配终止并返回；反之开始查找 <code>^~</code>或<code>无</code>，按最长匹配(而不是指令出现的顺序)为条件</li>
<li>如果最长前缀修饰词是<code>^~</code>，匹配终止并返回</li>
<li>如果最长前缀无修饰词，暂存结果，进入<code>正则匹配</code></li>
<li>按指令出现的顺序依次匹配<code>正则表达式</code>，若结果为真，则匹配并返回；反之，则将之前暂存的结果返回。</li>
<li>没有成功匹配任何条件，则返回第一条指令结果
</font>
为啥是这个结论？ 请看下面内容……</li>
</ol>
<p><a href="http://nginx.org/en/docs/http/ngx_http_core_module.html#location">Nginx官方文档</a>是这么解释的</p>
<blockquote>
<p>A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.</p>
</blockquote>
<p>翻译下就是，一个location指令可以实现<code>前缀匹配</code>和<code>正则匹配</code>。正则匹配里又分两种，即<code>~</code>和<code>~*</code>，后者不区分大小写。给定一个请求路径，nginx首先检查所有的<code>前缀字符串</code>。在他们之中，最长的会被<strong>选中并暂存</strong>。如果前缀未匹配到，则按照<code>出现的顺序</code>进行<code>正则匹配</code>。如果正则匹配结果为真，则终止匹配返回结果；反之，取<code>前缀匹配</code>中的结果返回。</p>
<p>也就是说，<code>前缀匹配</code>即使选中了，也不一定是最终结果！它只是做暂存。如果打破这个呢？ <code>^~</code>可以实现这个。匹配上它后，nginx不在匹配任何正则。</p>
<p>另外一个特殊的是 `=``，一旦精确匹配上，匹配也终止！</p>
<blockquote>
<p>Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates</p>
</blockquote>
<p>举个例子</p>
<div class="highlight"><pre><span></span><span class="n">location</span> <span class="o">/</span><span class="n">abc</span> <span class="p">{</span>
    <span class="p">[</span><span class="n">config</span> <span class="n">A</span><span class="p">]</span>
<span class="p">}</span>

<span class="n">location</span> <span class="o">~</span> <span class="o">^/</span><span class="n">abc</span> <span class="p">{</span>
    <span class="p">[</span><span class="n">config</span> <span class="n">B</span><span class="p">]</span>
<span class="p">}</span>
</pre></div>


<p>如果请求url为<code>xxx.com/abc</code>，则最终会匹配 config B</p>
<div class="highlight"><pre><span></span><span class="n">location</span> <span class="o">~</span> <span class="o">^/</span><span class="n">abc</span> <span class="p">{</span>
    <span class="p">[</span><span class="n">config</span> <span class="n">B</span><span class="p">]</span>
<span class="p">}</span>

<span class="n">location</span> <span class="o">^~</span> <span class="o">/</span><span class="n">abc</span> <span class="p">{</span>
    <span class="p">[</span><span class="n">config</span> <span class="n">C</span><span class="p">]</span>
<span class="p">}</span>
</pre></div>


<p>如果请求url为<code>xxx.com/abc</code>,则最终匹配 config C
注意，如果是下面的配置，会报错</p>
<div class="highlight"><pre><span></span>location /abc {}
location ^~ /abc {}
</pre></div>


<p>报错如下：<code>nginx: [emerg] duplicate location "/abc" in /etc/nginx/nginx.conf:132</code></p>
<h1>声明</h1>
<p>转载请注明出处 http://www.ddkiss.com</p>
            </div>
            <div class="post_list">
              <div><span>Tags : </span>
              </div>
            </div>
        </article>
        <div id="container"></div>
        <script type="text/javascript" src="//dn-coding-net-public-file.qbox.me/Coding-Comments/v0.1.0/gitment.min.js"></script>
        <script>
            var gitment = new Gitment({
              owner: 'whusl',
              repo: 'BlogComments',
              oauth: {
                client_id: '621866266817529fba46681653017809',
                client_secret: '14188411740b12ae52159cee9b586bf85cd54125',
              },
            })
            document.getElementById('container').appendChild(gitment.render())
          </script>
    </section>
</article>

<!-- Footer -->
    <footer>
        <p> &copy;2017-2020&nbsp;<a href="http://www.miitbeian.gov.cn/" target="_blank">鄂ICP备17020200号</a>
          Blog powered by <a href="http://getpelican.com/">Pelican</a>
        </p>
    </footer>

    <!-- Analytics -->
    <script>
      var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?88c55edaf311dbacac56a16316b04c8b";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
      })();
    </script>

<script type="text/javascript">(function(){document.write(unescape('%3Cdiv id="bdcs"%3E%3C/div%3E'));var bdcs = document.createElement('script');bdcs.type = 'text/javascript';bdcs.async = true;bdcs.src = 'http://znsv.baidu.com/customer_search/api/js?sid=14490611060029767912' + '&plate_url=' + encodeURIComponent(window.location.href) + '&t=' + Math.ceil(new Date()/3600000);var s = document.getElementsByTagName('script')[0];s.parentNode.insertBefore(bdcs, s);})();</script>

</body>
</html>